package cn.iocoder.yudao.module.system.service.agent;


import cn.iocoder.yudao.framework.common.enums.RequestUriEnum;
import cn.iocoder.yudao.module.system.controller.admin.agent.vo.PostJdReqVO;
import cn.iocoder.yudao.module.system.util.agent.CustomInfoBuild;
import cn.iocoder.yudao.module.system.util.agent.SelectRulesUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ffcs.ebp.ebpsdk.common.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;

/**
 * @author cxy
 * @date 2024/07/24
 */
@Service
@Slf4j
public class AgentServiceImpl implements AgentService {

    @Value("${apiproxy.isPlatformSpecificResource}")
    private String isPlatformSpecificResource;

    @Value("${apiproxy.userChannelLimitation}")
    private String userChannelLimitation;

    @Value("${apiproxy.billingOwner}")
    private Integer billingOwner;

    @Value("${apiproxy.autoRenewStatus}")
    private Integer autoRenewStatus;

    @Value("${apiproxy.autoRenewCycleType}")
    private Integer autoRenewCycleType;

    @Value("${apiproxy.autoRenewCycleCount}")
    private Integer autoRenewCycleCount;

    @Value("${apiproxy.instanceCnt}")
    private Integer instanceCnt;

    @Value("${apiproxy.cycleCnt}")
    private Integer cycleCnt;

    @Value("${apiproxy.cycleType}")
    private Integer cycleType;

    @Value("${apiproxy.master}")
    private Boolean master;

    @Value("${apiproxy.resourceType}")
    private String resourceType;

    @Value("${apiproxy.serviceTag}")
    private String serviceTag;

    @Value("${apiproxy.itemValue}")
    private Integer itemValue;

    @Value("${apiproxy.gpu}")
    private String gpu;




    @Autowired
    RequestService requestService;

    /**
     * 天翼云 https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=81&api=2270&data=31&isNormal=1云桌面订购
     * orderDetailJson
     *      isPlatformSpecificResource 是否特定平台，取值范围：true 或false 为true表示是特定平台资源，则userChannelLimitation不能为空，资源可操作平台请参照userChannelLimitation取值范围
     *      userChannelLimitation 资源可操作平台。当is_platform_specific为true时,userChannelLimitation不能为空。取值范围：1、2、3、4、5 （1：只允许通过省crm进行操作 2：只允许通过集团crm进行操作 3：只允许通过分销商进行操作 4：只允许crm客户个人操作（天翼云官网、个人api、app、微信小程序） 5：只允许通过省门户cmp进行操作）如需要支持多个平台进行操作，传参示例为"1,4,5"
     *      billingOwner出账方 取值范围 1 和 2。 为1 表示云公司出账； 为2表示省公司出账。 默认为1 （云公司出账）。默认续订、升级、退订都是直接继承新购时传的出账方字段值。
     *      autoRenewStatus 自动续订状态 （0-不自动续订,1-自动续订）
     *      autoRenewCycleType 自动续订周期类型，取值范围：3表示按月订购，5表示按一年订购，6表示按两年订购、7表示按三年订购。autoRenewCycleCount属性为1，autoRenewCycleType取值为3 表示订购1个月。
     *      autoRenewCycleCount 自动续订周期时长，取值范围：值需大于零，不超过384个月
     *      *order
 *               *instanceCnt 订购数量，取值范围：值需大于零
 *               *cycleCnt 订购周期，取值范围：值需大于零小于3，不超过3个月
 *               *cycleType 订购周期类型，取值范围：固定参数3，3表示按月订购，cycleCnt属性为1表示订购1个月
 *               *items 订单项信息
 *                   *master
 *                   *resourceType 资源类型，自研通用版云桌面BUSINESS_CPC_VM
 *                   *serviceTag 资源服务标签，自研通用版云桌面BUSINESS_CPC
 *                   *itemValue
 *                   *itemConfig
 *                      sysVolumeType 系统盘类型（根据[查询云桌面主机规格信息](#16-2)接口获取返回结果里的sales.sysVolumeType
 *                      memSize	 主机内存大小，请根据[查询云桌面主机规格信息](#16-2)接口返回值进行传参
 *                      type 带宽类型，取值范围：standalone 带宽类型只支持standalone（独享带宽）类型
 *                      sysVolumeSize	 系统盘大小（根据[查询云桌面主机规格信息](#16-2)接口获取返回结果里的sales.sysVolumeSize）
 *                      version	 	版本
 *                      cpuNum	 主机cpu核数，请根据[查询云桌面主机规格信息](#16-2)接口返回值进行传参
 *                      availability_zone  资源池可用区，请根据[查询资源池](#16-25)接口返回值进行传参，获取此zoneId参数
 *                      subnetId 	子网id，请根据[查询子网列表](#16-23)接口返回值进行传参，获取“resVlanId”参数。注：（如果没有子网需要先去创建子网[创建子网](#16-22) ）
 *                      userEmail	 userEmail
 *                      userGroup	 userGroup
 *                      userName	 userName
 *                      os	 	os
 *                      regionId regionId
     *       customInfo
     *          name	客户名字
     *          email	客户邮箱
     *          phone	客户电话
     *          type 	客户类型，type为空或0时，使用accessKey匹配的用户做为订单的客户标识；为1时，使用identity中的crmBizId匹配的用户做为订单的客户标识；为2时，使用identity中的accountId作为订单用户的标识	2
     *          *identity		身份信息
     *              userId 	用户id
     *              accountId 	客户对应云公司账户的accountId，type传2则必须传此值，该值主要用于第三方合作客户
     *              crmBizId 	云网账号接入号，type传1则必须传此值，该值主要用于省公司crm用户
     *
     * @param createReqVO
     * @return
     */
    @Override
    public String jdOrderFinishV2(PostJdReqVO createReqVO) {

//        用户信息可以不填，默认使用的是ak对应的用户
//        CustomInfoBuild customInfoBuild = new CustomInfoBuild(createReqVO.getUserName(),createReqVO.getUserEmail(),createReqVO.getPhone(),"x","x","x","x");
//        Map<String, Object> customInfoAndIdentity =customInfoBuild.buildCustomInfoAndIdentity();
        CustomInfoBuild customInfoBuild = new CustomInfoBuild();
        Map<String, Object> customInfoAndIdentity =customInfoBuild.buildNullCustomInfo();


        //1.调用apiproxy_查询云桌面资源池得到一个资源池列表，优先区天津3资源池。todo:天津3可能会使用完。后续逻辑需要处理
        //type为0或null时其他参数可以不传。使用accessKey匹配的用户做为订单的客户标识； 当type为1时，使用identity中的crmBizId匹配的用户做为订单的客户标识；为2时，使用identity中的accountId作为订单用户的标识
        //Map<String, Object> customInfoMap =customInfoBuild.buildCustomInfoAndIdentity();
        Map<String, Object> headerMap1 = customInfoBuild.buildHeader1(customInfoAndIdentity);
        Map<String,Object> regionMap = queryWorkSpaceRegions(headerMap1);
        customInfoBuild.setRegionId(regionMap.get("regionId").toString());

        //2.查询云桌面主机规格信息(融合) 得到 系统盘类型sysVolumeType、内存大小memSize、系统盘大小sysVolumeSize、版本version、cpu核数cpuNum
        Map<String, Object> headerMap2 =customInfoBuild.buildHeader2(customInfoAndIdentity,gpu);
        Map<String,String> templateMap = queryCloudDesktopFlavors(headerMap2);

        //3.查询vpc列表，返回可用的vpc.
        Map<String, Object> headerMapVpc =customInfoBuild.buildHeader2(customInfoAndIdentity,null);
        Map<String, Object> vpcs = getVpcs(headerMapVpc);
        Object resVpcIdObj = vpcs.get("resVpcId");
        String resVpcId =null;
        if (resVpcIdObj != null){
             resVpcId = resVpcIdObj.toString();
        }
        //3.调用apiproxy_查询子网列表 得到子网id
        Map<String, Object> headerMap4 =customInfoBuild.buildHeader4(customInfoAndIdentity,resVpcId);
        String subnetId = getSubnets(headerMap4);

        //构建调用云桌面订购(通用)接口入参。NEW_DESKTOP
        Map<String, Object> orderDetailJsonMap = buildOrderDetail(createReqVO,templateMap,regionMap,subnetId);
        String body = JSONObject.toJSONString(orderDetailJsonMap);
        String s = newDesktop(null, body);

        return null;
    }

    private Map<String, Object> buildOrderDetail(PostJdReqVO createReqVO,Map<String, String> templateMap,Map<String, Object> regionMap,String subnetId) {
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("isPlatformSpecificResource",isPlatformSpecificResource);
        resMap.put("userChannelLimitation",userChannelLimitation);
        resMap.put("billingOwner",billingOwner);
        resMap.put("autoRenewStatus",autoRenewStatus);
        resMap.put("autoRenewCycleType",autoRenewCycleType);
        resMap.put("autoRenewCycleCount",autoRenewCycleCount);
        resMap.put("orders",getOrderMap(createReqVO,templateMap,regionMap,subnetId));

        return null;
    }
    //构建orderMap
    private Map<String, Object> getOrderMap(PostJdReqVO createReqVO,Map<String, String> templateMap,Map<String, Object> regionMap,String subnetId) {
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("instanceCnt", instanceCnt);
        resMap.put("cycleCnt", cycleCnt);
        resMap.put("cycleType", cycleType);
        Map<String, Object> itemsMap = new HashMap<>();
        itemsMap.put("master", master);
        itemsMap.put("resourceType", resourceType);
        itemsMap.put("serviceTag", serviceTag);
        itemsMap.put("itemValue", itemValue);
        itemsMap.put("itemConfig", getItemConfigMap(templateMap,regionMap,subnetId));
        resMap.put("items", itemsMap);
        return resMap;
    }
    private Map<String, String> getItemConfigMap(Map<String, String> templateMap,Map<String, Object> regionMap,String subnetId) {
        Map<String, String> resMap = new HashMap<>();
        resMap.put("sysVolumeType", templateMap.get("sysVolumeType"));
        resMap.put("memSize", templateMap.get("memSize"));
        resMap.put("sysVolumeSize", templateMap.get("sysVolumeSize"));
        resMap.put("version", templateMap.get("version"));
        resMap.put("cpuNum", templateMap.get("cpuNum"));
        resMap.put("regionId", regionMap.get("regionId").toString());
        resMap.put("zoneId", regionMap.get("zoneId").toString());
        resMap.put("subnetId", subnetId);
        return resMap;
    }






    //订购云桌面

    @Override
    public String newDesktop(Map<String, Object> headerMap, String body) {
        Response response = requestService.getResponse(RequestUriEnum.NEW_DESKTOP, headerMap, body, "");
        //如果返回是900说明创建失败。
            //失败原因：子网IP余量不足够。 需要在对应的VPC下创建新的子网。每个vpc下能创建五个子网。如果子网用尽需要创建新的vpc和子网。

        return null;
    }



    //查询云桌面资源池
    @Override
    public Map<String,Object> queryWorkSpaceRegions(Map<String, Object> headerMap) {
        Map<String,Object> resMap = new HashMap<>();
        //query参数（？后面拼接的参数。没有就不填）
        String queryStr = "";
        //body参数（没有就不填）
        String body = "";
        Response response = requestService.getResponse(RequestUriEnum.QUERY_WORK_SPACE_REGIONS, headerMap, body, queryStr);
        if(response.getStatusCode() == 800 ){
           String res = response.getBody();
            if(StringUtils.isNotBlank(res)){
                List<Map<String, Object>> regionsMap = JSONObject.parseObject(body, new TypeReference<List<Map<String, Object>>>(){});
                resMap = SelectRulesUtils.spaceRegionsRule(regionsMap);
            }
        }
        return resMap;
    }

    //查询VPC列表（融合）v4
    @Override
    public Map<String, Object> getVpcs(Map<String, Object> headerMap) {
        Map<String,Object> resMap = new HashMap<>();
        Response response = requestService.getResponse(RequestUriEnum.GET_VPCS, headerMap, "", "");
        if(response.getStatusCode() == 800 ){
            String body = response.getBody();
            if(StringUtils.isNotBlank(body)){
                List<Map<String, Object>> vpcs = JSONObject.parseObject(body, new TypeReference<List<Map<String, Object>>>(){});
                resMap = SelectRulesUtils.vpcRule(vpcs);
            } else {
                //结果为null。调用创建vpc接口。
                //创建成vpc之后直接调用创建子网接口。
            }
        }else{
            //vpc查询失败，需要重新查询。
        }
        return resMap;
    }


    @Override
    public String createDefaultVPC(Map<String, Object> headerMap, String body) {
        Response response = requestService.getResponse(RequestUriEnum.CREATE_DEFAULT_VPC, headerMap, body, "");
        return null;
    }





    @Override
    public String queryVPCDetail(Map<String, Object> headerMap) {
        Response response = requestService.getResponse(RequestUriEnum.QUERY_VPC_DETAIL, headerMap, "", "");
        return null;
    }

    @Override
    public String createSubnet(Map<String, Object> headerMap, String body) {
        Response response = requestService.getResponse(RequestUriEnum.CREATE_SUBNET, headerMap, body, "");
        return null;
    }

    /**
     * 查询子网列表(融合) 。
     * 需要根据vpc查询，首先调用vpc列表查询可用的vpc.
     * 可以根据接口测试一下不传vpcid的时候返回的是什么结果。如果返回的是全部子网。就可以不查询vpc.如果子网用尽之后直接调用创建vpc就行。
     * @param headerMap
     * @return
     */
    @Override
    public String getSubnets(Map<String, Object> headerMap) {
        String resVlanId = null;
        Response response = requestService.getResponse(RequestUriEnum.GET_SUBNETS, headerMap, "", "");
        if(response.getStatusCode() == 800 ){
            //todo: 之后会调用子网剩余ip数量的接口。目前未提供。如果数量为0.直接调用创建。
            String body = response.getBody();
            if(StringUtils.isNotBlank(body)){
                List<Map<String, Object>> vlans = JSONObject.parseObject(body, new TypeReference<List<Map<String, Object>>>(){});
                 resVlanId  = SelectRulesUtils.subnetRule(vlans);


            } else {
                 //创建子网。
            }
        }else{
            //vpc查询失败，需要重新查询。
        }
        return resVlanId;
    }

    @Override
    public String createCloudDesktopService(Map<String, Object> headerMap, String body) {
        Response response = requestService.getResponse(RequestUriEnum.CREATE_CLOUD_DESKTOP_SERVICE, headerMap, body, "");
        return null;
    }

    @Override
    public String getWorkspaceJob(Map<String, Object> headerMap) {
        Response response = requestService.getResponse(RequestUriEnum.GET_WORK_SPACE_JOB, headerMap, "", "");
        return null;
    }

    /**
     * 查询云桌面主机规格信息(融合)
     * @param headerMap
     * @return
     */
    @Override
    public  Map<String,String>  queryCloudDesktopFlavors(Map<String, Object> headerMap) {
        Map<String,String> resMap = new HashMap<>();
        Response response = requestService.getResponse(RequestUriEnum.QUERY_CLOUD_DESKTOP_FLAVORS, headerMap, "", "");
        if(response.getStatusCode() == 800 ){
                resMap = JSON.parseObject(response.getBody(), Map.class);
                //规格需要根据京东的规格id查询对应的规格信息。确定使用哪一个规格。需要所有字段都匹配。
                //todo: 确定规格中type具体是什么值。
        }else{
            //规格查询失败，订单创建失败
        }
        return resMap;
    }

    @Override
    public String getImages(Map<String, Object> headerMap) {
        Response response = requestService.getResponse(RequestUriEnum.GET_IMAGES, headerMap, "", "");
        return null;
    }


    /**
     * 文档更新接口废弃，使用jdOrderFinishV2替代
     * @param createReqVO
     * @return
     */
    @Override
    public String jdOrderFinish(PostJdReqVO createReqVO) {
        /*
            order接口需要参数：
            京东提供 orderId、orderNo、prodInstId、
            租户信息 accountId、userId、email、 ak\sk
            京东提供 userEmail、userName、userAccount、
            天翼云接口可得到 regionId、azId、templateId、mirrorId、vpcId、subnetId、
            无具体加密方式 sysDiskList、diskList、
            不清楚是什么busiChannel、prodId、extJson
         */

        //1.调用apiproxy_查询云桌面资源池得到一个资源池列表，取第一个得到 资源池id regionId 和 可用区域 zoneId；
        //type为0或null时其他参数可以不传。使用accessKey匹配的用户做为订单的客户标识； 当type为1时，使用identity中的crmBizId匹配的用户做为订单的客户标识；为2时，使用identity中的accountId作为订单用户的标识
        CustomInfoBuild customInfoBuild = new CustomInfoBuild(createReqVO.getUserName(),createReqVO.getUserEmail(),createReqVO.getPhone(),"x","x","x","x");
        Map<String, Object> customInfoMap =customInfoBuild.buildCustomInfoAndIdentity();
        Map<String, Object> headerMap1 = customInfoBuild.buildHeader1(customInfoMap);
        Map<String,Object> resMap = queryWorkSpaceRegions(headerMap1);
        String regionId = resMap.get("regionId").toString();
        String zoneId = resMap.get("zoneId").toString();

        //2.调用apiproxy_云电脑规格查询（仅用于查询templateId（规格id）） 得到 规格id templateId
        Map<String, Object> customInfoAndIdentity =customInfoBuild.buildCustomInfoAndIdentity();
        Map<String, Object> headerMap2 =customInfoBuild.buildHeader2(customInfoAndIdentity,gpu);
        Map<String,String> templateId = queryCloudDesktopFlavors(headerMap2);


        //3.调用apiproxy_查询云桌面私有镜像列表（融合） 得到 镜像id。
        Map<String, Object> headerMap3 = customInfoBuild.buildHeader3(customInfoAndIdentity);
        String mirrorId = getImages(headerMap3);

        //4.调用apiproxy_查询VPC详情（融合） 得到 VPCId。
        Map<String, Object> headerMap4 =customInfoBuild.buildHeader4(customInfoAndIdentity,null);
        String vpcId = queryVPCDetail(headerMap4);


        //5.调用apiproxy_查询子网详情（融合） 得到子网id
        headerMap4.put("subnetId", "xxxxxxxxxxxxxxx");
        String subnetId = getSubnets(headerMap4);

        //6.创建云桌面服务 createCloudDesktopService
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("orderId",createReqVO.getOrderId());
        requestBody.put("orderNo",createReqVO.getOrderNo());
        requestBody.put("prodInstId","x");
        requestBody.put("accountId","x");
        requestBody.put("userId","x");
        requestBody.put("email","x");
        requestBody.put("userEmail",createReqVO.getUserEmail());
        requestBody.put("userName",createReqVO.getUserName());
        requestBody.put("userAccount",createReqVO.getUserAccount());
        requestBody.put("regionId",regionId);
        requestBody.put("azId",zoneId);
        requestBody.put("templateId",templateId);
        requestBody.put("mirrorId",mirrorId);
        requestBody.put("sysDiskList","x");
        requestBody.put("diskList","x");
        requestBody.put("vpcId",vpcId);
        requestBody.put("subnetId",subnetId);
        requestBody.put("busiChannel","x");
        requestBody.put("prodId","x");
        requestBody.put("extJson","x");
        String body = JSONObject.toJSONString(requestBody);
        Response response = requestService.getResponse(RequestUriEnum.ORDER, null, body, "");
        return null;
    }

}
